using System;
using System.Collections.Generic;
using System.Text;
using System.Resources;
using System.Reflection;
using System.IO;
using System.Net;
using System.Windows.Forms;
using System.Collections;
using System.Diagnostics;

namespace RandomGenerationFramework
{
	[Flags()]
	public enum CharacterType
	{
		Space = 1,
		Digit = 2,
		UpperCase = 4,
		LowerCase = 8,
		Symbol = 16
	}

	[Flags()]
	public enum NameType
	{
		MaleName = 1,
		FemaleName = 2,
		Surname = 4,
		Word = 8
	}


	public abstract class RandomGeneratorBase<T>
	{
		protected Random _random = new Random(int.Parse(Guid.NewGuid().ToString().Substring(0, 8), System.Globalization.NumberStyles.HexNumber));
		public abstract T GetRandom();
	}
    public class CharRandomGen : RandomGeneratorBase<Char>
    {
        private static Hashtable characterset = new Hashtable();
        private int _min;
        private int _max;

        public CharRandomGen()
        {
            _min = 0;
            _max = 51;

            if (!(characterset.Count > 0))
            {

                characterset.Add(1, 'A');
                characterset.Add(2, 'B');
                characterset.Add(3, 'C');
                characterset.Add(4, 'D');
                characterset.Add(5, 'E');
                characterset.Add(6, 'F');
                characterset.Add(7, 'G');
                characterset.Add(8, 'H');
                characterset.Add(9, 'I');
                characterset.Add(10, 'J');
                characterset.Add(11, 'K');
                characterset.Add(12, 'L');
                characterset.Add(13, 'M');
                characterset.Add(14, 'N');
                characterset.Add(15, 'O');
                characterset.Add(16, 'P');
                characterset.Add(17, 'Q');
                characterset.Add(18, 'R');
                characterset.Add(19, 'S');
                characterset.Add(20, 'T');
                characterset.Add(21, 'U');
                characterset.Add(22, 'V');
                characterset.Add(23, 'W');
                characterset.Add(24, 'X');
                characterset.Add(25, 'Y');
                characterset.Add(26, 'Z');
                characterset.Add(27, 'a');
                characterset.Add(28, 'b');
                characterset.Add(29, 'c');
                characterset.Add(30, 'd');
                characterset.Add(31, 'e');
                characterset.Add(32, 'f');
                characterset.Add(33, 'g');
                characterset.Add(34, 'h');
                characterset.Add(35, 'i');
                characterset.Add(36, 'j');
                characterset.Add(37, 'k');
                characterset.Add(38, 'l');
                characterset.Add(39, 'm');
                characterset.Add(40, 'n');
                characterset.Add(41, 'o');
                characterset.Add(42, 'p');
                characterset.Add(43, 'q');
                characterset.Add(44, 'r');
                characterset.Add(45, 's');
                characterset.Add(46, 't');
                characterset.Add(47, 'u');
                characterset.Add(48, 'v');
                characterset.Add( 49 , 'w');
                characterset.Add( 50 , 'x');
                characterset.Add( 51 , 'y');
                characterset.Add( 52 , 'z');
            }
        }

        public override char GetRandom()
        {
            IntegerRandomGenerator ig = new IntegerRandomGenerator(_min, _max);
            return (char) characterset[ig.GetRandom()];
        }
    }


    public class ByteRandomGen : RandomGeneratorBase<Byte[]>
    {

        private int _min;
        private int _max;

        public ByteRandomGen(int maxlength)
		{
			_min = 0;
            _max = maxlength;
		}

        public override Byte[] GetRandom()
        {
            // generate a random length Binary 
            IntegerRandomGenerator ig = new IntegerRandomGenerator(_min, _max);
            int lengthofBin = ig.GetRandom();
            Byte[] bytetemp = new Byte[lengthofBin];
            // get an array of random numbers from the service equivalent to the length of bin
            ArrayList list = RandomGeneratorHelper.GetRandomInteger(0, 10000, lengthofBin);
            for (int i = 0; i < lengthofBin; i++)
                bytetemp.SetValue(list[i], i);
            return bytetemp;
        }
    }

    public class GuidRandomGen : RandomGeneratorBase<Guid>
    {
        public GuidRandomGen()
        {
        }

        public override Guid GetRandom()
        {
            return Guid.NewGuid();
        }
    }

	public class BooleanRandonGen : RandomGeneratorBase<bool>
	{

		public override bool GetRandom()
		{
			return (_random.NextDouble() >= 0.5);
		}

	}
	public class IntegerRandomGenerator : RandomGeneratorBase<int>
	{
		private int _min;
		private int _max;

		public IntegerRandomGenerator(int min, int max)
		{
			_min = min;
			_max = max;
		}

		public override int GetRandom()
		{
			return _random.Next(_min, _max);
		}

	}
	public class DoubleRandomGenerator : RandomGeneratorBase<double>
	{
		private double _min;
		private double _max;

		public DoubleRandomGenerator(double min, double max)
		{
			_min = min;
			_max = max;
		}

		public override double GetRandom()
		{
			return ((_max - _min) * _random.NextDouble()) + _min;
		}


	}
	public class StringRandomGenerator : RandomGeneratorBase<string>
	{
		private char[] _chars;
		private int _min = 0;
		private int _max = 0;
		private bool _padRight = DEFAULT_PAD_RAIGHT;
		private const bool DEFAULT_PAD_RAIGHT = false;

		public StringRandomGenerator(int maxLength, CharacterType charType)
			: this(0, maxLength, charType, DEFAULT_PAD_RAIGHT) { }

		public StringRandomGenerator(int maxLength, CharacterType charType, bool padRight)
			: this(0, maxLength, charType, padRight) { }

		public StringRandomGenerator(int minLength, int maxLength, CharacterType charType)
			: this(minLength, maxLength, charType, DEFAULT_PAD_RAIGHT) { }

		public StringRandomGenerator(int minLength, int maxLength, CharacterType charType, bool padRight)
		{
			_min = minLength;
			_max = maxLength;
			_chars = RandomGeneratorHelper.GetChars(charType);
			_padRight = padRight;
		}

        //public override string GetRandom()
        //{
        //    int n = 0;
        //    if (_min == _max)
        //    {
        //        n = _max;
        //    }
        //    else
        //    {
        //        n = GetRandomLength();
        //    }
        //    StringBuilder sb = new StringBuilder();
        //    for (int i = 0; i <= n - 1; i++)
        //    {
        //        sb.Append(GetRandomChar());
        //    }
        //    if (_padRight)
        //    {
        //        return sb.ToString().PadRight(_max);
        //    }
        //    else
        //    {
        //        return sb.ToString();
        //    }
        //}

        /// <summary>
        /// modified code so Random service trip is reduced
        /// </summary>
        /// <returns></returns>
        public override string GetRandom()
        {
            int n = 0;
            if (_min == _max)
            {
                n = _max;
            }
            else
            {
                //get random length of the string to create for this call
                n = GetRandomLength();
            }
            StringBuilder sb = new StringBuilder();
            //n number of rand numbers to generate a char for 
            ArrayList a =  RandomGeneratorHelper.GetRandomInteger(0, _chars.GetUpperBound(0), n);
            foreach(int i in  a)
                sb.Append(GetRandomChar(i));
            if (_padRight)
            {
                return sb.ToString().PadRight(_max);
            }
            else
            {
                return sb.ToString();
            }
        }

        /// <summary>
        /// modified code so Random service trip is reduced
        /// </summary>
        /// <returns></returns>
        public string GetRandom(int stringlength)
        {
            int n = 0;
            ArrayList a = null;

            try
            {
                if (_min == _max)
                {
                    n = _max;
                }
                else
                {
                    //get random length of the string to create for this call
                    n = stringlength;
                }
                StringBuilder sb = new StringBuilder();
                //n number of rand numbers to generate a char for 
                a = RandomGeneratorHelper.GetRandomInteger(0, _chars.GetUpperBound(0), n);
                Debug.WriteLine("Returned from STRING CHAR service call at  " + DateTime.Now.ToString("HH:mm:ss"));
                foreach (int i in a)
                    sb.Append(GetRandomChar(i));
                if (_padRight)
                {
                    return sb.ToString().PadRight(_max);
                }
                else
                {
                    return sb.ToString();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (a != null)
                    a = null;
            }
        }

        /// <summary>
        /// modified code so Random service trip is reduced
        /// </summary>
        /// <returns></returns>
        public string GetRandom(int stringlength, ArrayList b)
        {
            int n = 0;
            ArrayList a = b;
            try
            {
                if (_min == _max)
                {
                    n = _max;
                }
                else
                {
                    //get random length of the string to create for this call
                    n = stringlength;
                }
                StringBuilder sb = new StringBuilder();
                //n number of rand numbers to generate a char for 
               // Debug.WriteLine("Returned from STRING CHAR service call at  " + DateTime.Now.ToString("HH:mm:ss"));
                foreach (int i in a)
                    sb.Append(GetRandomChar(i));
                if (_padRight)
                {
                    return sb.ToString().PadRight(_max);
                }
                else
                {
                    return sb.ToString();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if(a!=null)
                a=null;
            }
        }

		private int GetRandomLength()
		{
			return RandomGeneratorHelper.GetRandomInteger(_min, _max + 1);
		}

        //private int GetRandomLength( int nummax)
        //{
        //    return RandomGeneratorHelper.GetRandomInteger(_min, _max + 1, nummax);
        //}

		public char GetRandomChar()
		{            //November 4th, I removed the plus one 
         //   int rnd = RandomGeneratorHelper.GetRandomInteger(0, _chars.GetUpperBound(0) + 1);
			int rnd = RandomGeneratorHelper.GetRandomInteger(0, _chars.GetUpperBound(0));
			return _chars[rnd];
		}

        public char GetRandomChar(int charindex)
        {            //November 8th, To skip having to go back to the database to get a random number when constructing a text or strings
            return _chars[charindex];
        }
	}
	public class RandomGeneratorHelper
	{
		private static Random _random = new Random(System.DateTime.Now.Millisecond * System.DateTime.Now.Second);
        private static ArrayList randnums = new ArrayList();

		public static int GetRandomInteger()
		{
			return GetRandomInteger(true);
		}

        //public static int GetRandomInteger( int nummaxs)
        //{
        //    return GetRandomInteger(true, nummaxs);
        //}

		public static int GetRandomInteger(bool onlyPositive)
		{
			if (onlyPositive)
			{
				return GetRandomInteger(0, int.MaxValue);
			}
			else
			{
				return GetRandomInteger(int.MinValue, int.MaxValue);
			}
		}
        //public static int GetRandomInteger(bool onlyPositive, int nummaxs)
        //{
        //    //if (onlyPositive)
        //    //{
        //    //    return GetRandomInteger(0, int.MaxValue, nummaxs);
        //    //}
        //    //else
        //    //{
        //    //    return GetRandomInteger(int.MinValue, int.MaxValue, nummaxs);
        //    //}
        //}

		public static int GetRandomInteger(int min, int max)
		{

            // add the code to retrieve the truly random number from service here 
            String url = "http://www.random.org/integers/?num=1&min=" + min + "&max=" + max + "&col=5&base=10&format=html&rnd=new";
            WebRequest request = WebRequest.Create(url);
            // If required by the server, set the credentials.
            request.Credentials = CredentialCache.DefaultCredentials;
            // Get the response.
            HttpWebResponse response = (HttpWebResponse) request.GetResponse();
            // Display the status.
         //   Console.WriteLine(response.StatusDescription);
            // Get the stream containing content returned by the server.
            Stream dataStream = response.GetResponseStream();
            // Open the stream using a StreamReader for easy access.
            StreamReader reader = new StreamReader(dataStream);
            // Read the content.
            string responseFromServer = reader.ReadToEnd();

            //locate the string 
            string tocheck = @"<pre class=""data"">";
            int begincheckat = responseFromServer.IndexOf(tocheck) + tocheck.Length;
            int endreadindex = responseFromServer.IndexOf("</pre>");
            // read the content.
            int result = 0;
            if (responseFromServer.Length > endreadindex)
            {
                result = Convert.ToInt32(responseFromServer.Substring(begincheckat, endreadindex - begincheckat).Trim());
            }
            //  MessageBox.Show( responseFromServer);
            // Cleanup the streams and the response.
            reader.Close();
            dataStream.Close();
            response.Close();
            Debug.WriteLine("Returned from service call at  "  + DateTime.Now.ToString("HH:mm:ss"));
            return result;
                 //return _random.Next(min, max);
         
		}

        public static ArrayList GetRandomInteger(int min, int max,int maxcountofrecords)
        {

            // add the code to retrieve the truly random number from service here 
            String url = "http://www.random.org/integers/?num=" + maxcountofrecords +"&min=" + min + "&max=" + max + "&col=5&base=10&format=html&rnd=new";
            WebRequest request = WebRequest.Create(url);
            // If required by the server, set the credentials.
            request.Credentials = CredentialCache.DefaultCredentials;
            // Get the response.
            HttpWebResponse response = (HttpWebResponse) request.GetResponse();
            // Display the status.
          //  Console.WriteLine(response.StatusDescription);
            // Get the stream containing content returned by the server.
            Stream dataStream = response.GetResponseStream();
            // Open the stream using a StreamReader for easy access.
            StreamReader reader = new StreamReader(dataStream);
            // Read the content.
            string responseFromServer = reader.ReadToEnd();

            //locate the string 
            string tocheck = @"<pre class=""data"">";
            int begincheckat = responseFromServer.IndexOf(tocheck) + tocheck.Length;
            int endreadindex = responseFromServer.IndexOf("</pre>");
            // read the content.
           ArrayList result = new ArrayList();
            if (responseFromServer.Length > endreadindex)
            {
                String tempresponse =  responseFromServer.Substring(begincheckat, (endreadindex - begincheckat));
                String[] temp = tempresponse.Split(new char[] { '\t', '\n' });  
                 foreach(string a in temp) 
                     if( ! String.IsNullOrEmpty(a))
                     result.Add(Convert.ToInt32(a.Trim()));
            }
            //  MessageBox.Show( responseFromServer);
            // Cleanup the streams and the response.
            reader.Close();
            dataStream.Close();
            response.Close();

            return result;
           //return _random.Next(min, max);

        }

        //public static int GetRandomInteger(int min, int max, int nummax)
        //{
        //    randnums = new ArrayList(nummax);
        //    // add the code to retrieve the truly random number from service here 
        //    String url = "http://www.random.org/integers/?num=" + nummax + "&min=" + min + "&max=" + max + "&col=5&base=10&format=html&rnd=new";
        //    WebRequest request = WebRequest.Create(url);
        //    // If required by the server, set the credentials.
        //    request.Credentials = CredentialCache.DefaultCredentials;
        //    // Get the response.
        //    HttpWebResponse response = (HttpWebResponse) request.GetResponse();
        //    // Display the status.
        //    Console.WriteLine(response.StatusDescription);
        //    // Get the stream containing content returned by the server.
        //    Stream dataStream = response.GetResponseStream();
        //    // Open the stream using a StreamReader for easy access.
        //    StreamReader reader = new StreamReader(dataStream);
        //    // Read the content.
        //    string responseFromServer = reader.ReadToEnd();

        //    //locate the string 
        //    string tocheck = @"<pre class=""data"">";
        //    int begincheckat = responseFromServer.IndexOf(tocheck) + tocheck.Length;
        //    int endreadindex = responseFromServer.IndexOf("</pre>");
        //    // read the content.
        //    int result = 0;
        //    if (responseFromServer.Length > endreadindex)
        //    {
        //        result = Convert.ToInt32(responseFromServer.Substring(begincheckat, endreadindex - begincheckat).Trim());
        //    }
        //    //  MessageBox.Show( responseFromServer);
        //    // Cleanup the streams and the response.
        //    reader.Close();
        //    dataStream.Close();
        //    response.Close();

        //    return result;
        //    //return _random.Next(min, max);

        //}

        public static int GetID(int min, int max)
		{
            // add the code to retrieve the truly random number from service here 
            String url = "http://www.random.org/integers/?num=1&min=" + min + "&max=" + max + "&col=5&base=10&format=html&rnd=new";
            WebRequest request = WebRequest.Create(url);
            // If required by the server, set the credentials.
            request.Credentials = CredentialCache.DefaultCredentials;
            // Get the response.
            HttpWebResponse response = (HttpWebResponse) request.GetResponse();
            // Display the status.
            Console.WriteLine(response.StatusDescription);
            // Get the stream containing content returned by the server.
            Stream dataStream = response.GetResponseStream();
            // Open the stream using a StreamReader for easy access.
            StreamReader reader = new StreamReader(dataStream);
            // Read the content.
            string responseFromServer = reader.ReadToEnd();

            //locate the string 
            string tocheck = @"<pre class=""data"">";
            int begincheckat = responseFromServer.IndexOf(tocheck) + tocheck.Length;
            int endreadindex = responseFromServer.IndexOf("</pre>");
            // read the content.
            int result = 0;
            if (responseFromServer.Length > endreadindex)
            {
                result = Convert.ToInt32(responseFromServer.Substring(begincheckat, endreadindex - begincheckat).Trim());
            }
            //  MessageBox.Show( responseFromServer);
            // Cleanup the streams and the response.
            reader.Close();
            dataStream.Close();
            response.Close();

            return result;
                // return _random.Next(min, max);
         
		}

		public static char[] GetChars(CharacterType cht)
        {
       
                char[] ch = null;
                try
                {
                    if ((cht & CharacterType.Digit) > 0)
                    {
                        ch = ReziseAndAppendCharArray(ch, GetDigits());
                    }
                    if ((cht & CharacterType.UpperCase) > 0)
                    {
                        ch = ReziseAndAppendCharArray(ch, GetUpperCase());
                    }
                    if ((cht & CharacterType.LowerCase) > 0)
                    {
                        ch = ReziseAndAppendCharArray(ch, GetLowerCase());
                    }
                    if ((cht & CharacterType.Space) > 0)
                    {
                        char[] spc = { ' ' };
                        ch = ReziseAndAppendCharArray(ch, spc);
                    }
                    if ((cht & CharacterType.Symbol) > 0)
                    {
                        char[] spc = GetChars("!-/*");
                        ch = ReziseAndAppendCharArray(ch, spc);
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                return ch;
          
		}

		private static char[] ReziseAndAppendCharArray(char[] mainArray, char[] toBeCopiedArray)
        {

            try
            {
                if (mainArray == null)
                {
                    mainArray = toBeCopiedArray;
                }
                else
                {
                    int oldLength = mainArray.Length;
                    char[] newArray = new char[oldLength + toBeCopiedArray.Length];
                    Array.Copy(mainArray, 0, newArray, 0, oldLength);
                    Array.Copy(toBeCopiedArray, 0, newArray, oldLength, toBeCopiedArray.Length);
                    mainArray = newArray;
                }
                return mainArray;
            }
            catch (Exception ex)
            {
                throw ex;
            }
           
		}

		private static char[] GetChars(string charRange)
        {

            try
            {
                string[] ss = charRange.Split('-');
                char ch1 = ss[0][0];
                char ch2 = ss[1][0];
                char[] ch = new char[Convert.ToInt32(ch2) - Convert.ToInt32(ch1) + 1];
                for (int i = Convert.ToInt32(ch1); i <= Convert.ToInt32(ch2); i++)
                {
                    ch[i - Convert.ToInt32(ch1)] = Convert.ToChar(i);
                }
                return ch;
            }
            catch (Exception ex)
            {
                throw ex;
            }
      
		}

		private static char[] GetDigits()
		{
            try
            {
                char[] ch = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
                return ch;
            }
            catch (Exception ex)
            {
                throw ex;
            }
		}

		private static char[] GetUpperCase()
        {
       
                char[] ch = new char[26];
                try
                {
                    int A_ASC_VALUE = Convert.ToInt32('A');
                    for (int i = A_ASC_VALUE; i < A_ASC_VALUE + 26; i++)
                    {
                        ch[i - A_ASC_VALUE] = Convert.ToChar(i);
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                return ch;
     
		}

        private static char[] GetLowerCase()
        {
    
                char[] ch = new char[26];
                try
                {
                    int A_ASC_VALUE = Convert.ToInt32('a');
                    for (int i = A_ASC_VALUE; i < A_ASC_VALUE + 26; i++)
                    {
                        ch[i - A_ASC_VALUE] = Convert.ToChar(i);
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                return ch;
      
        }
	}
	public class ListRandomGenerator<T> : RandomGeneratorBase<T>
	{

		private IList<T> _list = new List<T>();
		private bool _unique = false;

		public ListRandomGenerator(IList<T> list) : this(list, false, false) { }

		public ListRandomGenerator(IList<T> list, bool unique, bool makeLocalCopyOfList)
		{

			_unique = unique;

            try
            {
                if (unique && makeLocalCopyOfList)
                {
                    // make a copy 
                    _list = new List<T>();
                    foreach (T o in list)
                        _list.Add(o);
                }
                else
                    _list = list;
            }
            catch (Exception ex)
            {
                throw ex;
            }

		}

		public override T GetRandom()
		{
            try
            {
                if (_unique)
                {
                    if (_list.Count == 0)
                        throw new InvalidOperationException("The list is exhausted. No more unique items could be returned.");
                    int index = base._random.Next(0, _list.Count);
                    T o = _list[index];
                    _list.RemoveAt(index);
                    return o;
                }
                else
                    return _list[base._random.Next(0, _list.Count)];
            }
            catch (Exception ex)
            {
                throw ex;
            }
		}
	}

	public class PrioritisedListRandomGenerator<T> : RandomGeneratorBase<T>
	{
		private List<T> _list = new List<T>();

		public PrioritisedListRandomGenerator(IList<T> items, int maxScore)
		{
            try
            {
                foreach (T item in items)
                {
                    for (int i = 0; i < _random.Next(1, maxScore); i++)
                        _list.Add(item);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
		}

		public PrioritisedListRandomGenerator(Dictionary<T, int> itemAsKeyIntegerScoreAsValue)
		{

            try
            {
                foreach (T key in itemAsKeyIntegerScoreAsValue.Keys)
                {
                    int count = itemAsKeyIntegerScoreAsValue[key];
                    for (int i = 0; i < count; i++)
                        _list.Add(key);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
		}

		public override T GetRandom()
		{
			return _list[base._random.Next(0, _list.Count)];
		}
	}
	public class DateRandomGenerator : RandomGeneratorBase<DateTime>
	{

		private long _minDate = DateTime.MinValue.Ticks;
		private long _maxDate = DateTime.Now.Ticks;

		public DateRandomGenerator() : this(DateTime.MinValue, DateTime.Now) { }

		public DateRandomGenerator(DateTime minDate) : this(minDate, DateTime.Now) { }

		public DateRandomGenerator(DateTime minDate, DateTime maxDate)
		{
			_minDate = minDate.Ticks;
			_maxDate = maxDate.Ticks;
		}

		public override DateTime GetRandom()
		{
			return new DateTime((long)((_random.NextDouble() * (_maxDate - _minDate)) + _minDate));
		}

	}
	public class NameRandomGenerator : RandomGeneratorBase<string>
	{
		private IList<string> _list;

		public NameRandomGenerator(NameType type)
		{
			_list = NameCache.GetList(type);
		}

		public override string GetRandom()
		{
			return _list[base._random.Next(0, _list.Count)];
		}


		private class NameCache
		{
			private static Dictionary<NameType, List<string>> _nameLists = new Dictionary<NameType, List<string>>();
			private static List<string> _maleNames = new List<string>();
			private static List<string> _femaleNames = new List<string>();
			private static List<string> _surnames = new List<string>();
			private static List<string> _words = new List<string>();


			public static List<string> GetList(NameType type)
			{
                try
                {
                    if (!_nameLists.ContainsKey(type))
                    {
                        _nameLists.Add(type, GetMixedNameList(type));
                    }
                    return (List<string>) _nameLists[type];
                }
                catch (Exception ex)
                {
                    throw ex;
                }

			}

			private static List<string> GetMixedNameList(NameType type)
			{
				List<string> al = new List<string>();
                try
                {
                    if ((type & NameType.MaleName) == NameType.MaleName)
                    {
                        FillListFromList(al, MaleNames);
                    }
                    if ((type & NameType.FemaleName) == NameType.FemaleName)
                    {
                        FillListFromList(al, FemaleNames);
                    }
                    if ((type & NameType.Surname) == NameType.Surname)
                    {
                        FillListFromList(al, Surnames);
                    }
                    if ((type & NameType.Word) == NameType.Word)
                    {
                        FillListFromList(al, Words);
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }

				return al;
			}

			public static List<string> MaleNames
			{
				get
				{
					if (_maleNames.Count == 0)
					{
						FillList(_maleNames, NameType.MaleName);
					}
					return _maleNames;
				}
			}

			public static List<string> FemaleNames
			{
				get
				{
					if (_femaleNames.Count == 0)
					{
						FillList(_femaleNames, NameType.FemaleName);
					}
					return _femaleNames;
				}
			}

			public static List<string> Surnames
			{
				get
				{
					if (_surnames.Count == 0)
					{
						FillList(_surnames, NameType.Surname);
					}
					return _surnames;
				}
			}

			public static List<string> Words
			{
				get
				{
					if (_words.Count == 0)
					{
						FillList(_words, NameType.Word);
					}
					return _words;
				}
			}

			public static void FillList(List<string> list, NameType type)
			{
                try
                {
                    switch (type)
                    {
                        case NameType.MaleName:
                            FillListFromResource(list, "RandomGenerationFramework.MaleName.txt", false);
                            break;
                        case NameType.FemaleName:
                            FillListFromResource(list, "RandomGenerationFramework.FemaleName.txt", false);
                            break;
                        case NameType.Surname:
                            FillListFromResource(list, "RandomGenerationFramework.Surname.txt", false);
                            break;
                        case NameType.Word:
                            FillListFromResource(list, "RandomGenerationFramework.Word.txt", false);
                            break;

                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
			}

			private static void FillListFromResource(List<string> list, string resourceName, bool truncate)
			{
                try
                {
                    Assembly ass = Assembly.GetExecutingAssembly();
                    StreamReader sr = new StreamReader(ass.GetManifestResourceStream(resourceName));
                    while (sr.Peek() >= 0)
                    {
                        string line = sr.ReadLine();
                        if (truncate)
                            line = line.Split(' ')[0];
                        list.Add(line);
                    }
                    sr.Close();
                }
                catch (Exception ex)
                {
                    throw ex;
                }
			}

			private static void FillListFromList(List<string> destination, List<string> source)
			{
				foreach (string s in source)
					destination.Add(s);
			}

		}

	
	}
	public class EnumRandomGenerator<T> : ListRandomGenerator<T>
	{

		public EnumRandomGenerator()
			: base(new List<T>((IList<T>)Enum.GetValues(typeof(T))))
		{

		}


	}

}